package Viewer;

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Polygon;
import java.awt.RenderingHints;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;

import javax.swing.JPanel;

import DataModel.Tupel;

/**
 * The slider is a navigation tool in GeneScapes<br>
 * It consists of to knobs representing the start and stop position<br>
 * and a linking bar which represents the shown range of GeneScapes.<br>
 * These three widgets can be dragged with the mouse cursor to change <br>
 * position and range of GeneScapes.
 * 
 * @author Stefan Lorenz<br>
 * <br>29.11.2012
 */
@SuppressWarnings("serial")
public class SliderPanel extends JPanel implements MouseListener, MouseMotionListener {

    /**
     * Viewer of the GeneScapes session
     */
    private Viewer viewer;
    /**
     * Start position of the slider in the genome
     */
    private int start;
    /**
     * stop position of the slider in the genome
     */
    private int stop;
    /**
     * Is start knob moved?
     */
    private boolean moveStart;
    /**
     * Is stop knob moved?
     */
    private boolean moveEnd;
    /**
     * Is the middle bar of the slider moved?
     */
    private boolean moveRec;
    /**
     * Tupel which represent the taken distance
     */
    private Tupel xDist = new Tupel();
    /**
     * Start position on screen
     */
    private int startSlider;
    /**
     * Stop position on screen
     */
    private int stopSlider;

    /**
     * Constructor of the navigation slider
     * @param viewer
     *            viewer of the genescapes session
     */
    public SliderPanel(Viewer viewer) {
	this.viewer = viewer;
	this.setPreferredSize(new Dimension(this.viewer.getDrawPanel().getWidth(), 32));
	this.setFocusable(true);
	this.addMouseListener(this);
	this.addMouseMotionListener(this);

	update();
    }

    /* (non-Javadoc)
     * @see javax.swing.JComponent#paint(java.awt.Graphics)
     */
    public void paint(Graphics g) {
	super.paint(g);
	Graphics2D g2 = (Graphics2D) g;
	g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
	g2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_SPEED);
	this.setBackground(this.viewer.getSettings().getBackgroundColor());
	g2.setFont(new Font("arial", Font.BOLD, 10));
	g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
	g2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_SPEED);
	g2.setColor(this.viewer.getSettings().getLabelingColor());
	g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.3f));
	g2.fillRoundRect(startSlider, 11, stopSlider - startSlider, 8, 5, 15);
	g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1.0f));
	g2.drawRoundRect(startSlider, 11, stopSlider - startSlider, 8, 5, 15);

	// start stop line
	g2.drawLine(this.getWidth() - 1, 1, this.getWidth() - 1, 30);
	g2.drawLine(1, 1, 1, 30);

	// range lines
	Polygon p1 = new Polygon();
	p1.addPoint(1, 1);
	p1.addPoint(startSlider, 16);
	p1.addPoint(1, 30);

	Polygon p2 = new Polygon();
	p2.addPoint(this.getWidth() - 1, 1);
	p2.addPoint(stopSlider, 16);
	p2.addPoint(this.getWidth() - 1, 30);

	g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.2f));
	g2.fillPolygon(p1);
	g2.fillPolygon(p2);
	g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1.0f));
	g2.drawPolygon(p1);
	g2.drawPolygon(p2);

	if (startSlider > 0) {
	    g.setColor(new Color(28, 163, 138));
	    g2.fillOval(startSlider - 1, 10, 12, 12);
	    g2.setColor(this.viewer.getSettings().getLabelingColor());
	    g2.drawOval(startSlider - 1, 10, 12, 12);
	    g2.drawOval(startSlider - 1, 10, 12, 12);
	    g2.drawOval(startSlider + 2, 13, 6, 6);
	    g2.drawOval(startSlider + 2, 13, 6, 6);
	    g2.drawString(String.valueOf(this.start), startSlider + 5, 10);
	} else if (startSlider <= 0) {
	    g.setColor(new Color(28, 163, 138));
	    g2.fillOval(-1, 10, 12, 12);
	    g2.setColor(this.viewer.getSettings().getLabelingColor());
	    g2.drawOval(-1, 10, 12, 12);
	    g2.drawOval(-1, 10, 12, 12);
	    g2.drawOval(2, 13, 6, 6);
	    g2.drawOval(2, 13, 6, 6);
	    g2.drawString(String.valueOf(this.start), 5, 10);
	}
	if (stopSlider > this.getWidth()) {
	    g.setColor(new Color(28, 163, 138));
	    g2.fillOval(this.getWidth() - 5, 10, 12, 12);
	    g2.setColor(this.viewer.getSettings().getLabelingColor());
	    g2.drawOval(this.getWidth() - 5, 10, 12, 12);
	    g2.drawOval(this.getWidth() - 5, 10, 12, 12);
	    g2.drawOval(this.getWidth() - 2, 13, 6, 6);
	    g2.drawOval(this.getWidth() - 2, 13, 6, 6);
	    g2.drawString(String.valueOf(this.stop), this.getWidth() - 5 - 40, 30);
	} else if (stopSlider <= this.getWidth()) {
	    g.setColor(new Color(28, 163, 138));
	    g2.fillOval(stopSlider - 5, 10, 12, 12);
	    g2.setColor(this.viewer.getSettings().getLabelingColor());
	    g2.drawOval(stopSlider - 5, 10, 12, 12);
	    g2.drawOval(stopSlider - 5, 10, 12, 12);
	    g2.drawOval(stopSlider - 2, 13, 6, 6);
	    g2.drawOval(stopSlider - 2, 13, 6, 6);
	    g2.drawString(String.valueOf(this.stop), stopSlider - 40, 30);
	}

	if (!this.viewer.isEnabledViewer()) {
	    g2.setColor(Color.BLACK);
	    g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f));
	    g2.fillRect(0, 0, this.getWidth(), this.getHeight());
	    g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1.0f));
	}
    }

    /* (non-Javadoc)
     * @see java.awt.event.MouseMotionListener#mouseDragged(java.awt.event.MouseEvent)
     */
    public void mouseDragged(java.awt.event.MouseEvent e) {
	if (moveStart && e.getX() < stopSlider) {
	    int starti = (int) ((e.getX() / (float) this.getWidth()) * (float) this.viewer.getSizeOfReference());
	    int diff = this.stop - starti;
	    this.viewer.setRangeOfBrowser(diff);

	    for (int i = 0; i < viewer.getPositionOfTrack().length; i++) {
		starti = (int) ((e.getX() / (float) this.getWidth()) * (float) this.viewer.getSizeOfReference());
		this.viewer.setPositionOfBrowser(i, starti);
	    }
	    this.viewer.getDrawPanel().repaint();
	    return;
	} else if (moveEnd && e.getX() > startSlider) {
	    int stopi = (int) ((e.getX() / (float) this.getWidth()) * (float) this.viewer.getSizeOfReference());
	    int diff = stopi - this.start;
	    this.viewer.setRangeOfBrowser(diff);
	    this.viewer.getDrawPanel().repaint();
	    return;
	} else if (moveRec) {
	    for (int i = 0; i < viewer.getPositionOfTrack().length; i++) {
		int starti = (int) (((e.getX() - xDist.getStart()) / (float) this.getWidth()) * (float) this.viewer.getSizeOfReference());
		this.viewer.setPositionOfBrowser(i, starti);
	    }
	    this.viewer.setRangeOfBrowser(xDist.getStop());
	    this.viewer.getDrawPanel().repaint();
	    return;
	}
    }

    /* (non-Javadoc)
     * @see java.awt.event.MouseMotionListener#mouseMoved(java.awt.event.MouseEvent)
     */
    public void mouseMoved(java.awt.event.MouseEvent e) {
    }

    /* (non-Javadoc)
     * @see java.awt.event.MouseListener#mouseClicked(java.awt.event.MouseEvent)
     */
    public void mouseClicked(java.awt.event.MouseEvent e) {
	this.requestFocusInWindow();
    }

    /* (non-Javadoc)
     * @see java.awt.event.MouseListener#mousePressed(java.awt.event.MouseEvent)
     */
    public void mousePressed(java.awt.event.MouseEvent e) {
	this.moveStart = false;
	this.moveEnd = false;
	this.moveRec = false;

	xDist.setStart(e.getX() - this.startSlider);
	xDist.setStop(this.stop - this.start);

	if (e.getX() >= this.startSlider && e.getX() <= this.startSlider + 10 && e.getY() <= 22 && e.getY() >= 12) {
	    this.moveStart = true;
	} else if (e.getX() >= this.stopSlider - 5 && e.getX() <= this.stopSlider + 5 && e.getY() <= 22 && e.getY() >= 12) {
	    this.moveEnd = true;
	} else if (e.getX() < this.stopSlider - 5 && e.getX() > this.startSlider + 5 && e.getY() >= 14 && e.getY() <= 20) {
	    this.moveRec = true;
	}
    }

    /* (non-Javadoc)
     * @see java.awt.event.MouseListener#mouseReleased(java.awt.event.MouseEvent)
     */
    public void mouseReleased(java.awt.event.MouseEvent e) {
	if (this.moveStart) {
	    this.viewer.setPositionOfBrowser(1, this.start);
	    this.viewer.setRangeOfBrowser(this.stop - this.start);

	}
	if (this.moveEnd) {
	    this.viewer.setRangeOfBrowser(this.stop - this.start);
	}
	if (moveRec) {
	    this.viewer.setPositionOfBrowser(1, this.start);
	}
	this.moveStart = false;
	this.moveEnd = false;
	this.moveRec = false;
    }

    /* (non-Javadoc)
     * @see java.awt.event.MouseListener#mouseEntered(java.awt.event.MouseEvent)
     */
    public void mouseEntered(java.awt.event.MouseEvent e) {
    }

    /* (non-Javadoc)
     * @see java.awt.event.MouseListener#mouseExited(java.awt.event.MouseEvent)
     */
    public void mouseExited(java.awt.event.MouseEvent e) {
    }

    /**
     * Updates the sliders position and repaints it
     */
    public void update() {
	this.start = this.viewer.getPositionOfBrowser(1);
	this.stop = this.viewer.getPositionOfBrowser(1) + this.viewer.getRangeOfBrowser();
	this.startSlider = (int) (((float) this.start / (float) this.viewer.getSizeOfReference()) * (float) this.getWidth());
	this.stopSlider = (int) (((float) this.stop / (float) this.viewer.getSizeOfReference()) * (float) this.getWidth());
	this.repaint();
    }
}
